// FacebookGroupsService.cs
// Facebook/Framework/Service
// Copyright (c) 2007, Nikhil Kothari. All Rights Reserved.
//

using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using Facebook.Service.Core;

namespace Facebook.Service {

    /// <summary>
    /// Represents the service APIs related to user groups on Facebook.
    /// </summary>
    public sealed class GroupsService {

        private FacebookSession _session;

        internal GroupsService(FacebookSession session) {
            Debug.Assert(session != null);
            _session = session;
        }

        /// <summary>
        /// Gets the Facebook group identified by the specified ID.
        /// </summary>
        /// <param name="groupID">The unique ID of the group.</param>
        /// <returns>The information about the specified group.</returns>
        public Group GetGroup(string groupID) {
            if (String.IsNullOrEmpty(groupID)) {
                throw new ArgumentNullException("groupID");
            }

            ICollection<Group> groups = GetGroups(new string[] { groupID }, null);
            if ((groups != null) && (groups.Count != 0)) {
                foreach (Group group in groups) {
                    return group;
                }
            }
            return null;
        }

        /// <summary>
        /// Gets the list of Facebook groups identified by the specified IDs.
        /// </summary>
        /// <param name="groupIDs">The list of IDs of the groups.</param>
        /// <returns>The information about the specified groups.</returns>
        public ICollection<Group> GetGroups(ICollection<string> groupIDs) {
            if ((groupIDs == null) || (groupIDs.Count == 0)) {
                throw new ArgumentNullException("groupIDs");
            }

            return GetGroups(groupIDs, null);
        }

        /// <summary>
        /// Gets the list of Facebook groups associated with the user if a user is specified.
        /// </summary>
        /// <param name="groupIDs">The list of IDs of the groups.</param>
        /// <param name="userID">The unique ID of the user if the list of the groups is to be filtered by the user.</param>
        /// <returns>The information about the specified groups.</returns>
        public ICollection<Group> GetGroups(ICollection<string> groupIDs, string userID) {
            if (String.IsNullOrEmpty(userID) &&
                ((groupIDs == null) || (groupIDs.Count == 0))) {
                throw new ArgumentException("Must specify either groupIDs or userID");
            }

            FacebookRequest request = new FacebookRequest(_session);
            if (String.IsNullOrEmpty(userID) == false) {
                request.Parameters["uid"] = userID;
            }
            if (groupIDs != null) {
                StringBuilder idListBuilder = new StringBuilder();
                foreach (string id in groupIDs) {
                    if (idListBuilder.Length != 0) {
                        idListBuilder.Append(",");
                    }
                    idListBuilder.Append(id);
                }
                request.Parameters["gids"] = idListBuilder.ToString();
            }

            FacebookResponse response = request.InvokeMethod("groups.get");
            if (response.Status == FacebookResponseStatus.Succeeded) {
                List<Group> groups;

                if (response.Result is ArrayList) {
                    ArrayList groupListState = (ArrayList)response.Result;

                    groups = new List<Group>(groupListState.Count);
                    foreach (Hashtable groupState in groupListState) {
                        groups.Add(new Group(groupState));
                    }
                }
                else if (response.Result is Hashtable) {
                    groups = new List<Group>(1);
                    groups.Add(new Group((Hashtable)response.Result));
                }
                else {
                    groups = new List<Group>(0);
                }

                return groups;
            }

            return new Group[0];
        }

        /// <summary>
        /// Gets the list of Facebook groups that the user is a member of.
        /// </summary>
        /// <param name="userID">The unique ID of the user.</param>
        /// <returns>The information about the specified groups.</returns>
        public ICollection<Group> GetGroupsByUser(string userID) {
            if (String.IsNullOrEmpty(userID)) {
                throw new ArgumentNullException("userID");
            }

            return GetGroups(null, userID);
        }

        /// <summary>
        /// Gets the membership information for the specified group. This corresponds to the
        /// Facebook groups.getMembers method.
        /// </summary>
        /// <param name="groupID">The unique ID of the group.</param>
        /// <returns>The list of members of the specified group.</returns>
        public GroupMembership GetMembers(string groupID) {
            if (String.IsNullOrEmpty(groupID)) {
                throw new ArgumentNullException("groupID");
            }

            FacebookRequest request = new FacebookRequest(_session);
            request.Parameters["gid"] = groupID;

            FacebookResponse response = request.InvokeMethod("groups.getMembers");
            if (response.Status == FacebookResponseStatus.Succeeded) {
                Debug.Assert(response.Result is Hashtable);

                return new GroupMembership((Hashtable)response.Result);
            }

            return null;
        }
    }
}
